home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / tools / dynadraw.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  9KB  |  466 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /* 
  18.  *    dynadraw -
  19.  *
  20.  *         Use a simple dynamics model to create caligraphic strokes.
  21.  *
  22.  *    leftmouse   - used for drawing
  23.  *    middlemouse - clears page
  24.  *    rightmouse  - menu
  25.  *
  26.  *    uparrow     - wider strokes
  27.  *    downarrow   - narrower strokes
  28.  *
  29.  *                Paul Haeberli - 1989
  30.  *        
  31.  */
  32. #include <stdio.h>
  33. #include <math.h>
  34. #include <sys/types.h>
  35. #include <sys/times.h>
  36. #include <sys/param.h>
  37. #include <gl/gl.h>
  38. #include <gl/device.h>
  39.  
  40. #define SLIDERHIGH    (15)
  41. #define SLIDERLEFT    (200)
  42. #define TIMESLICE    (0.005)
  43. #define MAXPOLYS    (20000)
  44. #define SHRINK
  45.  
  46. typedef struct filter {
  47.      float curx, cury;
  48.      float velx, vely, vel;
  49.      float accx, accy, acc;
  50.      float angx, angy;
  51.      float mass, drag;
  52.      float lastx, lasty;
  53.      int fixedangle;
  54. } filter;
  55.  
  56. float initwidth = 1.5;
  57. float width, shrink;
  58. float odelx, odely;
  59. float curmass, curdrag;
  60. float polyverts[4*2*MAXPOLYS];
  61. int npolys;
  62. long xsize, ysize;
  63. long xorg, yorg;
  64. filter mouse;
  65.  
  66. float flerp();
  67. float fgetmousex();
  68. float fgetmousey();
  69. float gettime();
  70. unsigned long getltime();
  71.  
  72. filtersetpos(f,x,y)
  73. filter *f;
  74. float x, y;
  75. {
  76.     f->curx = x;
  77.     f->cury = y;
  78.     f->lastx = x;
  79.     f->lasty = y;
  80.     f->velx = 0.0;
  81.     f->vely = 0.0;
  82.     f->accx = 0.0;
  83.     f->accy = 0.0;
  84. }
  85.  
  86. filterapply(f,mx,my)
  87. filter *f;
  88. float mx, my;
  89. {
  90.     float mass, drag;
  91.     float fx, fy, force;
  92.  
  93. /* calculate mass and drag */
  94.     mass = flerp(1.0,160.0,curmass);
  95.     drag = flerp(0.00,0.5,curdrag*curdrag);
  96.  
  97. /* calculate force and acceleration */
  98.     fx = mx-f->curx;
  99.     fy = my-f->cury;
  100.     f->acc = sqrt(fx*fx+fy*fy);
  101.     if(f->acc<0.000001)
  102.     return 0;
  103.     f->accx = fx/mass;
  104.     f->accy = fy/mass;
  105.  
  106. /* calculate new velocity */
  107.     f->velx += f->accx;
  108.     f->vely += f->accy;
  109.     f->vel = sqrt(f->velx*f->velx+f->vely*f->vely);
  110.     f->angx = -f->vely;
  111.     f->angy = f->velx;
  112.     if(f->vel<0.000001) 
  113.      return 0;
  114.  
  115. /* calculate angle of drawing tool */
  116.     f->angx /= f->vel;
  117.     f->angy /= f->vel;
  118.     if(f->fixedangle) {
  119.     f->angx = 0.6;
  120.     f->angy = 0.2;
  121.     }
  122.  
  123. /* apply drag */
  124.     f->velx = f->velx*(1.0-drag);
  125.     f->vely = f->vely*(1.0-drag);
  126.  
  127. /* update position */
  128.     f->lastx = f->curx;
  129.     f->lasty = f->cury;
  130.     f->curx = f->curx+f->velx;
  131.     f->cury = f->cury+f->vely;
  132.     return 1;
  133. }
  134.  
  135. float paramval()
  136. {
  137.     float p;
  138.  
  139.     p = (float)(getmousex()-SLIDERLEFT)/(xsize-SLIDERLEFT);
  140.     if(p<0.0)
  141.     return 0.0;
  142.     if(p>1.0)
  143.     return 1.0;
  144.     return p;
  145. }
  146.  
  147. main()
  148. {
  149.     short val;
  150.     int menu, pres;
  151.     float p, mx, my;
  152.  
  153.     curmass = 0.5;
  154.     curdrag = 0.15;
  155.     prefsize(800,640);
  156.     initbuzz();
  157.     winopen("dynadraw");
  158.     glcompat(GLC_OLDPOLYGON,1);
  159.     subpixel(1);
  160.     shademodel(FLAT);
  161.     gconfig();
  162.     qdevice(LEFTMOUSE);
  163.     qdevice(MIDDLEMOUSE);
  164.     qdevice(MENUBUTTON);
  165.     qdevice(RIGHTSHIFTKEY); 
  166.     qdevice(UPARROWKEY); 
  167.     qdevice(DOWNARROWKEY); 
  168.     qdevice(RIGHTSHIFTKEY); 
  169.     makeframe();
  170.     menu = defpup("calligraphy %t|toggle line style|save ps|save image");
  171.     width = initwidth;
  172.     mouse.fixedangle = 1;
  173.     while(1) {
  174.     switch(qread(&val)) {
  175.         case REDRAW:
  176.         makeframe();
  177.         break;
  178.         case MIDDLEMOUSE:
  179.         if(val) 
  180.             clearscreen();
  181.         break;
  182.         case UPARROWKEY:
  183.         if(val) 
  184.             initwidth *= 1.414213;
  185.         width = initwidth;
  186.         break;
  187.         case DOWNARROWKEY:
  188.         if(val) 
  189.             initwidth /= 1.414213;
  190.         width = initwidth;
  191.         break;
  192.         case MENUBUTTON:
  193.         if(val) {
  194.             switch(dopup(menu)) {
  195.             case 1: 
  196.                 mouse.fixedangle = 1-mouse.fixedangle;
  197.                 break;
  198.             case 2: 
  199.                 savepolys();
  200.                 break;
  201.             case 3: 
  202.                 savewindow("drag.rgb");
  203.                 break;
  204.             }
  205.         }
  206.         break;
  207.         case LEFTMOUSE:
  208.         if(val) {
  209.             my = getmousey();
  210.             if(my>0*SLIDERHIGH && my<2*SLIDERHIGH) {
  211.             if(my>SLIDERHIGH) {
  212.                 while(getbutton(LEFTMOUSE)) {
  213.                 p = paramval();
  214.                 if(p != curmass) {
  215.                     curmass = p;
  216.                     showsettings();
  217.                 }
  218.                 }
  219.             } else {
  220.                 while(getbutton(LEFTMOUSE)) {
  221.                 p = paramval();
  222.                 if(p != curdrag) {
  223.                     curdrag = p;
  224.                     showsettings();
  225.                 }
  226.                 }
  227.             }
  228.             } else {
  229.             mx = 1.25*fgetmousex();
  230.             my = fgetmousey();
  231.             filtersetpos(&mouse,mx,my);
  232.             odelx = 0.0;
  233.             odely = 0.0;
  234.             shrink = 1.0;
  235.             while(getbutton(LEFTMOUSE)) {
  236.                 mx = 1.25*fgetmousex();
  237.                 my = fgetmousey();
  238.                 if(filterapply(&mouse,mx,my)) {
  239.                 drawsegment(&mouse);
  240.                 color(0);
  241.                 buzz();
  242.                 if(getbutton(RIGHTSHIFTKEY)) 
  243.                     shrink = shrink*0.98;
  244.                 }
  245.             }
  246.             }
  247.         }
  248.         break;
  249.     }
  250.     }
  251. }
  252.  
  253. makeframe()
  254. {
  255.     reshapeviewport();
  256.     getsize(&xsize,&ysize);
  257.     getorigin(&xorg,&yorg);
  258.     clearscreen();
  259. }
  260.  
  261. clearscreen()
  262. {
  263.     int x, y;
  264.  
  265.     ortho2(0.0,1.25,0.0,1.0);
  266.     color(51);
  267.     setpattern(0);
  268.     clear();
  269.     npolys = 0;
  270.     showsettings();
  271.     color(0);
  272. }
  273.  
  274. showsettings()
  275. {
  276.     char str[256];
  277.     int xpos;
  278.  
  279.     ortho2(-0.5,xsize-0.5,-0.5,ysize-0.5);
  280.     color(51);
  281.     rectfi(0,0,xsize,2*SLIDERHIGH);
  282.     color(0);
  283.     sprintf(str,"Mass %g",curmass); 
  284.     cmov2i(20,3+1*SLIDERHIGH);
  285.     charstr(str);
  286.     sprintf(str,"Drag %g",curdrag); 
  287.     cmov2i(20,3+0*SLIDERHIGH);
  288.     charstr(str);
  289.     move2i(SLIDERLEFT,0);
  290.     draw2i(SLIDERLEFT,2*SLIDERHIGH);
  291.     move2i(0,1*SLIDERHIGH);
  292.     draw2i(xsize,1*SLIDERHIGH);
  293.     move2i(0,2*SLIDERHIGH);
  294.     draw2i(xsize,2*SLIDERHIGH);
  295.     color(1);
  296.     xpos = SLIDERLEFT+curmass*(xsize-SLIDERLEFT);
  297.     rectfi(xpos,1*SLIDERHIGH,xpos+4,2*SLIDERHIGH);
  298.     xpos = SLIDERLEFT+curdrag*(xsize-SLIDERLEFT);
  299.     rectfi(xpos,0*SLIDERHIGH,xpos+4,1*SLIDERHIGH);
  300.     ortho2(0.0,1.25,0.0,1.0);
  301. }
  302.  
  303. drawsegment(f)
  304. filter *f;
  305. {
  306.     float delx, dely; 
  307.     float wid, *fptr;
  308.     float px, py, nx, ny;
  309.  
  310.     wid = 0.04-f->vel;
  311.     wid = wid*width;
  312.     if(wid<0.00001)
  313.         wid = 0.00001;
  314.     wid *= shrink;
  315.     delx = f->angx*wid;
  316.     dely = f->angy*wid;
  317.  
  318.     color(0);
  319.     px = f->lastx;
  320.     py = f->lasty;
  321.     nx = f->curx;
  322.     ny = f->cury;
  323.  
  324.     fptr = polyverts+8*npolys;
  325.     bgnpolygon();
  326.     fptr[0] = px+odelx;
  327.     fptr[1] = py+odely;
  328.     v2f(fptr);
  329.     fptr += 2;
  330.     fptr[0] = px-odelx;
  331.     fptr[1] = py-odely;
  332.     v2f(fptr);
  333.     fptr += 2;
  334.     fptr[0] = nx-delx;
  335.     fptr[1] = ny-dely;
  336.     v2f(fptr);
  337.     fptr += 2;
  338.     fptr[0] = nx+delx;
  339.     fptr[1] = ny+dely;
  340.     v2f(fptr);
  341.     fptr += 2;
  342.     endpolygon();
  343.     npolys++;
  344.     if(npolys>=MAXPOLYS) {
  345.     printf("out of polys - increase the define MAXPOLYS\n");
  346.     exit(1);
  347.     }
  348.     fptr -= 8;
  349.     bgnclosedline();
  350.     v2f(fptr);
  351.     fptr += 2;
  352.     v2f(fptr);
  353.     fptr += 2;
  354.     v2f(fptr);
  355.     fptr += 2;
  356.     v2f(fptr);
  357.     fptr += 2;
  358.     endclosedline();
  359.     odelx = delx;
  360.     odely = dely;
  361. }
  362.  
  363. int buzztemp, buzzmax;
  364.  
  365. buzz()
  366. {
  367.     int i;
  368.  
  369.     for(i=0; i<buzzmax; i++) 
  370.     buzztemp++;
  371. }
  372.  
  373. initbuzz()
  374. {
  375.     long t0, t1;
  376.  
  377.     buzzmax = 1000000;
  378.     sginap(10);
  379.     t0 = getltime();
  380.     buzz();
  381.     t1 = getltime();
  382.     buzzmax = TIMESLICE*(100.0*1000000.0)/(t1-t0);
  383. }
  384.  
  385. savepolys()
  386. {
  387.     FILE *of;
  388.     int i;
  389.     float *fptr;
  390.  
  391.     of = fopen("/tmp/drag.ps","w");
  392.     fprintf(of,"%%!\n");
  393.     fprintf(of,"%f %f translate\n",0.25*72,(11.0-0.75)*72);
  394.     fprintf(of,"-90 rotate\n");
  395.     fprintf(of,"%f %f scale\n",8.0*72,8.0*72);
  396.     fprintf(of,"0.0 setgray\n");
  397.     printf("npolys %d\n",npolys);
  398.     fptr = polyverts;
  399.     for(i=0; i<npolys; i++) {
  400.     fprintf(of,"newpath\n");
  401.     fprintf(of,"%f %f moveto\n",fptr[0],fptr[1]);
  402.     fptr+=2;
  403.     fprintf(of,"%f %f lineto\n",fptr[0],fptr[1]);
  404.     fptr+=2;
  405.     fprintf(of,"%f %f lineto\n",fptr[0],fptr[1]);
  406.     fptr+=2;
  407.     fprintf(of,"%f %f lineto\n",fptr[0],fptr[1]);
  408.     fptr+=2;
  409.     fprintf(of,"closepath\n");
  410.     fprintf(of,"fill\n");
  411.     }
  412.     fprintf(of,"showpage\n");
  413.     fclose(of);
  414.     fprintf(stderr,"PostScript saved to /tmp/drag.ps\n");
  415. }
  416.  
  417. /*
  418.  *    winlib routines follow
  419.  *
  420.  */
  421. float fgetmousex()
  422. {
  423.     return ((float)getvaluator(MOUSEX)-xorg)/(float)xsize;
  424. }
  425.  
  426. float fgetmousey()
  427. {
  428.     return ((float)getvaluator(MOUSEY)-yorg)/(float)ysize;
  429. }
  430.  
  431. int getmousex()
  432. {
  433.     return getvaluator(MOUSEX)-xorg;
  434. }
  435.  
  436. int getmousey()
  437. {
  438.     return getvaluator(MOUSEY)-yorg;
  439. }
  440.  
  441. float flerp(f0,f1,p)
  442. float f0, f1, p; 
  443. {
  444.     return ((f0*(1.0-p))+(f1*p));
  445. }
  446.  
  447. savewindow(name)
  448. char *name;
  449. {
  450.     char cmd[256];
  451.     long xorg, yorg;
  452.     long xsize, ysize;
  453.  
  454.     getorigin(&xorg,&yorg);
  455.     getsize(&xsize,&ysize);
  456.     sprintf(cmd,"scrsave %s %d %d %d %d\n",name,xorg,xorg+xsize-1,yorg,yorg+ysize-1);
  457.     system(cmd);
  458. }
  459.  
  460. unsigned long getltime()
  461. {
  462.     struct tms ct;
  463.  
  464.     return times(&ct);
  465. }
  466.